import { StatusCodes } from 'http-status-codes';
import BaseController from './BaseController.js';
import { createSendToken } from '../utils/jwt.js';
import db from '../models/index.js';
import { AppError } from '../middlewares/error.js';

const { User } = db;

class AuthController extends BaseController {
  constructor() {
    super();
  }

  /**
   * 用户注册
   */
  async register(req, res) {
    try {
      // 检查用户名和邮箱是否已存在
      const { username, email } = req.body;
      
      const existingUser = await User.findOne({
        where: {
          [User.Sequelize.Op.or]: [
            { username },
            { email }
          ]
        }
      });

      if (existingUser) {
        const field = existingUser.username === username ? '用户名' : '邮箱';
        return this.error(res, `${field}已存在`, StatusCodes.CONFLICT);
      }

      // 创建新用户
      const newUser = await User.create({
        ...req.body,
        role: User.ROLES.STUDENT // 默认注册为学生
      });

      // 生成JWT令牌并发送响应
      createSendToken(newUser, StatusCodes.CREATED, res);
    } catch (error) {
      this.error(res, '注册失败', StatusCodes.INTERNAL_SERVER_ERROR, error);
    }
  }

  /**
   * 用户登录
   */
  async login(req, res, next) {
    try {
      const { username, password } = req.body;

      // 1) 检查用户名和密码是否存在
      if (!username || !password) {
        return next(
          new AppError('请提供用户名和密码', StatusCodes.BAD_REQUEST)
        );
      }

      // 2) 检查用户是否存在且密码正确
      const user = await User.findOne({ where: { username } });

      if (!user || !(await user.validatePassword(password, user.password))) {
        return next(
          new AppError('用户名或密码错误', StatusCodes.UNAUTHORIZED)
        );
      }

      // 3) 检查用户是否被禁用
      if (!user.isActive) {
        return next(
          new AppError('该账户已被禁用，请联系管理员', StatusCodes.FORBIDDEN)
        );
      }

      // 4) 更新最后登录时间（暂时注释掉以避免权限问题）
      // user.lastLogin = new Date();
      // await user.save();

      // 5) 生成JWT令牌并发送响应
      createSendToken(user, StatusCodes.OK, res);
    } catch (error) {
      console.error('Login error:', error);
      return res.status(StatusCodes.INTERNAL_SERVER_ERROR).json({
        success: false,
        message: '登录失败',
        error: error.message
      });
    }
  }

  /**
   * 用户登出
   */
  logout(req, res) {
    res.cookie('token', 'loggedout', {
      expires: new Date(Date.now() + 10 * 1000), // 10秒后过期
      httpOnly: true,
    });

    this.success(res, null, '登出成功');
  }

  /**
   * 获取当前用户信息
   */
  getMe(req, res, next) {
    // req.user 由 protect 中间件添加
    this.success(res, req.user, '获取成功');
  }

  /**
   * 更新密码
   */
  async updatePassword(req, res, next) {
    try {
      // 1) 从请求中获取用户
      const user = await User.findByPk(req.user.id);

      // 2) 检查当前密码是否正确
      if (!(await user.validatePassword(req.body.currentPassword, user.password))) {
        return next(
          new AppError('当前密码错误', StatusCodes.UNAUTHORIZED)
        );
      }

      // 3) 更新密码
      user.password = req.body.newPassword;
      user.passwordChangedAt = Date.now() - 1000; // 确保令牌在密码更改后失效
      await user.save();

      // 4) 生成新的JWT令牌并发送响应
      createSendToken(user, StatusCodes.OK, res);
    } catch (error) {
      this.error(res, '密码更新失败', StatusCodes.INTERNAL_SERVER_ERROR, error);
    }
  }

  /**
   * 忘记密码 - 发送重置令牌
   */
  async forgotPassword(req, res, next) {
    try {
      // 1) 根据邮箱获取用户
      const user = await User.findOne({ where: { email: req.body.email } });
      
      if (!user) {
        return next(
          new AppError('该邮箱未注册', StatusCodes.NOT_FOUND)
        );
      }

      // 2) 生成重置令牌并保存到数据库
      const resetToken = user.createPasswordResetToken();
      await user.save({ validateBeforeSave: false });

      // 3) 发送重置链接到用户邮箱
      // 注意：实际项目中需要实现邮件发送功能
      const resetURL = `${req.protocol}://${req.get('host')}/api/v1/auth/reset-password/${resetToken}`;
      
      // 4) 返回成功响应（实际项目中应该发送邮件）
      this.success(res, 
        { resetToken, resetURL }, // 开发环境返回，生产环境不应返回
        '重置令牌已发送到您的邮箱',
        StatusCodes.OK
      );
    } catch (error) {
      // 重置令牌和过期时间
      user.passwordResetToken = undefined;
      user.passwordResetExpires = undefined;
      await user.save({ validateBeforeSave: false });

      this.error(
        res, 
        '发送重置邮件时出错，请稍后重试', 
        StatusCodes.INTERNAL_SERVER_ERROR, 
        error
      );
    }
  }

  /**
   * 重置密码
   */
  async resetPassword(req, res, next) {
    try {
      // 1) 获取基于令牌的用户
      const hashedToken = require('crypto')
        .createHash('sha256')
        .update(req.params.token)
        .digest('hex');

      const user = await User.findOne({
        where: {
          passwordResetToken: hashedToken,
          passwordResetExpires: { [User.Sequelize.Op.gt]: Date.now() }
        }
      });

      // 2) 如果令牌未过期且用户存在，设置新密码
      if (!user) {
        return next(new AppError('令牌无效或已过期', StatusCodes.BAD_REQUEST));
      }

      // 3) 更新密码
      user.password = req.body.password;
      user.passwordResetToken = null;
      user.passwordResetExpires = null;
      await user.save();

      // 4) 登录用户，发送JWT
      createSendToken(user, StatusCodes.OK, res);
    } catch (error) {
      this.error(res, '密码重置失败', StatusCodes.INTERNAL_SERVER_ERROR, error);
    }
  }
}

export default new AuthController();
